// Select2组件
function Select2Ctrl(id, urlOrData, key, value, type) {
    this.id = id;
    this.url = typeof(urlOrData) === "string" ? urlOrData : undefined;
    this.key = key;
    this.value = value;
    this.type = type;
    this.datas = typeof(urlOrData) === "string" ? [] : urlOrData;
    this.inited = false;

    this.onInitSuccess = function () {}

    this.init = function (defVul) {
        if (this.url) {
            this.initByUrl(this.url, defVul);
        } else {
            this.initByData(this.datas, defVul);
        }
    };

    this.initByUrl = function (url, defVul) {
        var self = this;
        self.url = url;
        $.ajax({
            url: self.url,
            type: HttpMethod.get,
            headers: {pageSize: MaxPageSize, pageNumber: 1},
            success: function (result, status, xhr) {
                self.initByData(result.records, defVul);
            }
        })
    };

    this.initByData = function (datas, defVul) {
        var self = this;
        self.datas = datas;
        if ("select2" === self.type) {
            var select2Datas = [];
            for (var i = 0; i < datas.length; i++) {
                var select2Data = {
                    id: datas[i][self.key],
                    text: datas[i][self.value]
                };
                select2Datas.push(select2Data);
            }
            if (self.inited) {
                $(self.id).select2("destroy").html("");
            }
            $(self.id).select2({data: select2Datas});
            $(self.id).val(defVul).trigger("change");
            self.inited = true;
        } else {
            var html = "";
            for (var i = 0; i < datas.length; i++) {
                html += "<option value='" + datas[i][self.key] + "'>" + datas[i][self.value] + "</option>"
            }
            $(self.id).html(html);
            $(self.id).val(defVul).trigger("change");
        }
        self.onInitSuccess();
    };

    this.setDisable = function () {
        $(this.id).prop('disabled', true);
    };

    this.setEnable = function () {
        $(this.id).prop('disabled', false);
    };

    this.empty = function () {
        var self = this;
        if ("select2" === type) {
            if (self.inited) {
                $(self.id).select2("destroy").html("");
            }
            $(self.id).select2({data: []}).val(null).trigger("change");
            self.inited = true;
        } else {
            $(self.id).html("");
        }
    };

    this.getById = function (id) {
        var data;
        for (var i = 0; i < this.datas.length; i++) {
            if (this.datas[i].id === id) {
                data = this.datas[i];
                break;
            }
        }
        return data;
    };

    this.getByIds = function (ids) {
        var datas = [];
        for (var i = 0; i < this.datas.length; i++) {
            if (ids.indexOf(this.datas[i].id) >= 0) {
                datas.push(this.datas[i]);
            }
        }
        return datas;
    };

    this.getIndex = function (id) {
        for (var i = 0; i < this.datas.length; i++) {
            if (this.datas[i].id === id) return i;
        }
        return undefined;
    };

    this.getIndexes = function (ids) {
        var indexs = [];
        for (var i = 0; i < ids.length; i++) {
            var index = this.getIndex(ids[i]);
            if (Utils.notEmpty(index)) indexs.push(index);
        }
        return indexs;
    };
}
// 通用CRUD组件
function TableCtrl(keywordUrl, detailUrl, createUrl, modifyUrl, removeUrl, dataBuilder, dataValidater, keywordSort, keywordOrder) {
    // 按关键字查询数据url
    this.keywordUrl = keywordUrl;
    // 按关键字查询排序字段
    this.keywordSort = keywordSort;
    // 按关键字查询排序顺序
    this.keywordOrder = keywordOrder;
    // 按id查询数据url
    this.detailUrl = detailUrl;
    // 创建数据url
    this.createUrl = createUrl;
    // 修改数据url
    this.modifyUrl = modifyUrl;
    // 删除数据url
    this.removeUrl = removeUrl;
    // 定义如何将数据在页面上展示，返回html
    this.dataBuilder = dataBuilder;
    // 新增或修改时执行校验，合法返回record，否则返回undefined
    this.dataValidater = dataValidater;
    // ===================== 上面是需要初始化的属性 ===================== //
    // 执行检索前针对url做扩展处理
    this.extraUrlSearch = function (url) {
        return url;
    };
    // 执行新增前针对url做扩展处理
    this.extraUrlCreate = function (url) {
        return url;
    };
    // 执行修改前针对url做扩展处理
    this.extraUrlModify = function (url, id) {
        return url;
    };
    // 执行删除前针对url做扩展处理
    this.extraUrlRemove = function (url, id) {
        return url;
    };
    // 执行详情前针对url做扩展处理
    this.extraUrlDetail = function (url, id) {
        return url;
    };
    // 扩展开始加载
    this.extraLoadStart = function () {};
    // 扩展加载完成
    this.extraLoadComplete = function () {};
    // 绑定其他事件
    this.extraBind = function () {};
    // 扩展显示创建页面
    this.extraShowCreate = function () {};
    // 扩展显示编辑页面
    this.extraShowModify = function (id) {};
    // 扩展页面回执
    this.extraSetRecord = function () {};
    // ===================== 上面是可选初始化的属性 ===================== //
    // 当前查询关键字
    this.keyword = "";
    // 当前查询页码
    this.pageNumber = 0;
    // 查询分页大小
    this.pageSize = 50;
    // 当前查询出来的所有数据，该数据和表格一致
    this.records = [];
    // 数据加载的html模板
    this.template = "";
    // 获取数据加载的html模板，并清空表格
    this.getTemplate = function () {
        this.template = $("#table > tbody").prop("innerHTML");
        $("#table > tbody").html("");
    };
    // 查询数据：查询关键字取keyword，查询页码为pageNumber+1，查询成功后累加records数据并将pageNumber+1，然后重新绘制表格
    this.getRecords = function () {
        var self = this;
        var url = this.keywordUrl + "?t=t";
        if (!Utils.isEmpty(this.keyword)) {
            url = url + "&keyword=" + encodeURIComponent(this.keyword);
        }
        url = this.extraUrlSearch(url);
        if (Utils.isEmpty(url)) {
            self.pageNumber = 1;
            self.records = [];
            self.setRecords();
            self.setLoadAll();
            self.setLoadComplete();
            return;
        }
        var headers = {
            pageSize: self.pageSize,
            pageNumber: self.pageNumber + 1
        };
        if (self.keywordSort) {
            headers.sort = self.keywordSort;
        }
        if (self.keywordOrder) {
            headers.order = self.keywordOrder;
        }
        $.ajax({
            url: url,
            type: HttpMethod.get,
            headers: headers,
            success: function (result, status, xhr) {
                self.pageNumber++;
                self.records = self.records.concat(result.records);
                self.setRecords();
                if (result.total > self.pageNumber * self.pageSize) {
                    self.setLoadMore();
                } else {
                    self.setLoadAll();
                }
            },
            error: function (xhr, error, exception) {
                self.setLoadError();
            },
            beforeSend: function (xhr) {
                self.setLoadStart();
            },
            complete: function (xhr, ts) {
                self.setLoadComplete();
            }
        })
    };
    // 重新绘制列表页面
    this.setRecords = function () {
        $("#table > tbody").html("");
        for (var i = 0; i < this.records.length; i++) {
            var record = this.records[i];
            var html = this.dataBuilder(this.template, record, i);
            $("#table > tbody").append(html);
        }
        if (this.extraSetRecord) {
            this.extraSetRecord();
        }
    };
    // 设置开始加载页面
    this.setLoadStart = function () {
        $("#load-more").hide();
        $("#load-all").hide();
        $("#load-error").hide();
        $("#loading").show();

        $("#search").attr("disabled", "disabled");
        this.extraLoadStart();
    };
    // 设置加载完成页面
    this.setLoadComplete = function () {
        $("#search").removeAttr("disabled");
        this.extraLoadComplete();
    };
    // 绘制是否还有更多数据页面
    this.setLoadMore = function (more) {
        $("#load-more").show();
        $("#load-all").hide();
        $("#load-error").hide();
        $("#loading").hide();
    };
    // 绘制已经加载全部数据页面
    this.setLoadAll = function (more) {
        $("#load-more").hide();
        $("#load-all").show();
        $("#load-error").hide();
        $("#loading").hide();
    };
    // 绘制加载失败页面
    this.setLoadError = function () {
        $("#load-more").hide();
        $("#load-all").hide();
        $("#load-error").show();
        $("#loading").hide();
    };
    // 按id到records中查询数据
    this.getById = function (id) {
        var record;
        for (var i = 0; i < this.records.length; i++) {
            if (this.records[i].id === id) {
                record = this.records[i];
                break;
            }
        }
        return record;
    };
    // 按id到records中更新数据
    this.refreshById = function (id, record) {
        var self = this;
        if (record) {
            for (var i = 0; i < this.records.length; i++) {
                if (this.records[i].id === id) {
                    this.records[i] = record;
                    break;
                }
            }
            this.setRecords();
        } else {
            var url = this.detailUrl.replace("{id}", id);
            url = this.extraUrlDetail(url, id);
            $.ajax({
                url: url,
                type: HttpMethod.get,
                success: function (result, status, xhr) {
                    self.refreshById(id, result);
                }
            })
        }
    };
    // 显示创建页面
    this.showCreate = function () {
        $("#detail select.select2").attr("data-dropdown-css-class", "select2-info").val(null).trigger("change")
            .removeClass("select2-danger").addClass("select2-info").select2();
        $("#detail input").removeClass("is-invalid").removeClass("is-valid").removeClass("is-warning").val("");
        this.extraShowCreate();
        $("#detail").removeClass("hide");
    };
    // 显示编辑页面
    this.showModify = function (id) {
        this.showCreate();
        var record = this.getById(id);

        $("#detail input").each(function (i, n) {
            var name = $(n).attr("name");
            if (!Utils.isEmpty(name)) {
                $(n).val(record[name]);
            }
        });

        $("#detail select").each(function (i, n) {
            var name = $(n).attr("name");
            if (!Utils.isEmpty(name)) {
                $(n).val(record[name]);
                if ($(n).hasClass("select2")) {
                    $(n).trigger("change");
                }
            }
        });

        this.extraShowModify(id);
        $("#detail").removeClass("hide");
    };
    // 非空判断
    this.checkRequire = function () {
        var valid = true;
        $("#detail select.select2").each(function (i, n) {
            if ($(n).attr("required") === "required" && Utils.isEmpty($(n).val())) {
                valid = false;
                $(n).attr("data-dropdown-css-class", "select2-danger")
                    .parent().removeClass("select2-info").addClass("select2-danger");
            } else {
                $(n).attr("data-dropdown-css-class", "select2-info")
                    .parent().removeClass("select2-danger").addClass("select2-info");
            }
        });
        $("#detail input").each(function (i, n) {
            if ($(n).attr("required") === "required" && Utils.isEmpty($(n).val())) {
                valid = false;
                $(n).removeClass("is-valid").addClass("is-invalid");
            } else {
                $(n).removeClass("is-invalid").addClass("is-valid");
            }
        });
        return valid;
    };
    // 调用后端接口保存数据，成功后更新页面
    this.save = function () {
        if (!this.checkRequire()) {
            return;
        }
        var record = this.dataValidater();
        var self = this;
        if (Utils.isEmpty(record)) {
            return;
        }
        if (Utils.isEmpty(record.id)) {
            var url = self.extraUrlCreate(self.createUrl);
            $.ajax({
                url: url,
                type: HttpMethod.post,
                contentType: ContentType.json,
                data: JSON.stringify(record),
                success: function (result, status, xhr) {
                    $("#detail").addClass("hide");
                    record = result;
                    self.records.push(record);
                    self.setRecords();
                    parent.window.frameCtrl.toastr.success("创建成功！");
                }
            });
        } else {
            var url = self.extraUrlModify(self.modifyUrl.replace("{id}", record.id), id);
            $.ajax({
                url: url,
                type: HttpMethod.put,
                contentType: ContentType.json,
                data: JSON.stringify(record),
                success: function (result, status, xhr) {
                    $("#detail").addClass("hide");
                    var index = self.records.indexOf(self.getById(record.id));
                    self.records[index] = result;
                    self.setRecords();
                    parent.window.frameCtrl.toastr.success("修改成功！");
                }
            });
        }
    };
    // 调用后端接口删除数据
    this.doRemove = function (id) {
        var self = this;
        var url = self.extraUrlRemove(self.removeUrl.replace("{id}", id), id);
        $.ajax({
            url: url,
            type: HttpMethod.delete,
            beforeSend: function (xhr) {
                $("#table .remove[data-id=" + id + "]").attr("disabled", "disabled");
            },
            success: function (result, status, xhr) {
                var record = self.getById(id);
                var index = self.records.indexOf(record);
                self.records.splice(index, 1);
                self.setRecords();
                parent.window.frameCtrl.toastr.success("删除成功！");
            },
            complete: function (xhr, ts) {
                $("#table .remove[data-id=" + id + "]").removeAttr("disabled");
            }
        });
    };
    // 调用后端接口删除数据，成功后更新页面
    this.remove = function (id) {
        var self = this;
        parent.window.frameCtrl.confirmCtrl.show("确认要删除该数据吗？", function () {
            self.doRemove(id);
        });
    };
    // 调用后端接口批量删除数据，成功后更新页面
    this.batchRemove = function () {
        var self = this;
        parent.window.frameCtrl.confirmCtrl.show("确认要批量删除这些数据吗？", function () {
            var ids = self.getChecked();
            for (let i = 0; i < ids.length; i++) {
                self.doRemove(ids[i]);
            }
        });
    }
    // 获取选中的数据ID列表
    this.getChecked = function () {
        var ids = [];
        $("#table tbody input:checked").each(function (i, n) {
            ids.push($(n).attr("data-id"));
        });
        return ids;
    };
    // 绑定页面事件
    this.bindEvent = function () {
        var self = this;
        // 绑定修改按钮
        $("#table").on("click", ".modify", function () {
            var id = $(this).attr("data-id");
            self.showModify(id);
        });
        // 绑定删除按钮
        $("#table").on("click", ".remove", function () {
            var id = $(this).attr("data-id");
            self.remove(id);
        });
        // 批量删除
        $("#batch-remove").click(function () {
            self.batchRemove();
        });
        // 绑定确定按钮
        $("#ok").bind("click", function () {
            self.save();
        });
        // 绑定取消按钮
        $("#cancel").bind("click", function () {
            $("#detail").addClass("hide");
        });
        // 绑定新增按钮
        $("#add").bind("click", function () {
            self.showCreate();
        });
        // 绑定加载更多数据
        $("#load-more").bind("click", function () {
            self.getRecords();
        });
        // 绑定搜索按钮
        $("#search").bind("click", function () {
            self.keyword = $("#keyword").val();
            self.pageNumber = 0;
            self.records = [];
            self.getRecords();
        });
        // 绑定勾选事件
        $("#table thead input:checkbox").bind("click", function () {
            $("#table tbody input:checkbox").prop("checked", $(this).prop("checked"));
        });
        // 绑定扩展事件
        this.extraBind();
    }
}

var frameCtrl = parent.window.frameCtrl;
var toastr = parent.window.toastr;